package com.daxt.utils;


import net.lingala.zip4j.core.ZipFile;
import net.lingala.zip4j.exception.ZipException;
import net.lingala.zip4j.model.FileHeader;
import net.lingala.zip4j.model.ZipParameters;
import net.lingala.zip4j.util.Zip4jConstants;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

/**
 * @description: zip文件，解压缩工具类
 *
 * @author: lig
 * @date: 2022/7/15
 */
public class ZipUtil {

    /**
     * 使用给定密码解压指定的ZIP压缩文件到指定目录
     * <p>
     * 如果指定目录不存在,可以自动创建,不合法的路径将导致异常被抛出
     * @param zip 指定的ZIP压缩文件
     * @param dest 解压目录
     * @param passwd ZIP文件的密码
     * @return 解压后文件数组
     * @throws ZipException 压缩文件有损坏或者解压缩失败抛出
     */
    public static File [] unzip(String zip, String dest, String passwd) throws ZipException {
        File zipFile = new File(zip);
        return unzip(zipFile, dest, passwd);
    }

    /**
     * 使用给定密码解压指定的ZIP压缩文件到当前目录
     * @param zip 指定的ZIP压缩文件
     * @param passwd ZIP文件的密码
     * @return  解压后文件数组
     * @throws ZipException 压缩文件有损坏或者解压缩失败抛出
     */
    public static File [] unzip(String zip, String passwd) throws ZipException {
        File zipFile = new File(zip);
        File parentDir = zipFile.getParentFile();
        return unzip(zipFile, parentDir.getAbsolutePath(), passwd);
    }

    /**
     * 使用给定密码解压指定的ZIP压缩文件到指定目录
     * <p>
     * 如果指定目录不存在,可以自动创建,不合法的路径将导致异常被抛出
     * @param zipFile 指定的ZIP压缩文件
     * @param dest 解压目录
     * @param passwd ZIP文件的密码
     * @return  解压后文件数组
     * @throws ZipException 压缩文件有损坏或者解压缩失败抛出
     */
    public static File [] unzip(File zipFile, String dest, String passwd) throws ZipException {
        // 首先创建ZipFile指向磁盘上的.zip文件
        ZipFile zFile = new ZipFile(zipFile);
        // 设置文件名编码，在GBK系统中需要设置
        //zFile.setFileNameCharset("GBK");
        zFile.setFileNameCharset("UTF-8");
        //判断压缩文件是否合法
        if (!zFile.isValidZipFile()) {
            throw new ZipException("压缩文件不合法,可能被损坏");
        }
        // 解压目录
        File destDir = new File(dest);
        if (destDir.isDirectory() && !destDir.exists()) {
            destDir.mkdir();
        }
        //判断密码是否为空
        boolean passwIsEmpty= StringUtils.isEmpty(passwd);
        if (!passwIsEmpty&&zFile.isEncrypted()) {
            //设置密码
            zFile.setPassword(passwd.toCharArray());
        }
        // 将文件抽出到解压目录(解压)
        zFile.extractAll(dest);

        List<FileHeader> headerList = zFile.getFileHeaders();
        List<File> extractedFileList = new ArrayList<>();
        for(FileHeader fileHeader : headerList) {
            if (!fileHeader.isDirectory()) {
                extractedFileList.add(new File(destDir,fileHeader.getFileName()));
            }
        }
        File [] extractedFiles = new File[extractedFileList.size()];
        extractedFileList.toArray(extractedFiles);
        return extractedFiles;
    }


    /**
     * 不加密的压缩
     * @param inputFile D:\\test  要打包的文件夹
     * @param outputFile  D:\test.zip  生成的压缩包的名字
     */
    public static void zipFile(String inputFile,String outputFile)  {
        // 生成的压缩文件
        ZipFile zipFile = null;
        try {
            zipFile = new ZipFile(outputFile);
            ZipParameters parameters = new ZipParameters();
            // 压缩方式
            parameters.setCompressionMethod(Zip4jConstants.COMP_DEFLATE);
            // 压缩级别
            parameters.setCompressionLevel(Zip4jConstants.DEFLATE_LEVEL_NORMAL);
            // 要打包的文件夹
            File currentFile = new File(inputFile);
            File[] fs = currentFile.listFiles();
            // 遍历test文件夹下所有的文件、文件夹
            for (File f : fs) {
                if (f.isDirectory()) {
                    zipFile.addFolder(f.getPath(), parameters);
                } else {
                    zipFile.addFile(f, parameters);
                }
            }
        } catch (ZipException e) {
            e.printStackTrace();
        }

    }


    /**
     * 压缩加密
     * @param inputFile  D:\\test  要打包的文件夹
     * @param outputFile  D:\test1.zip 生成的压缩包的名字
     */
    public static void ZipFileWithPwd(String inputFile,String outputFile) {
        // 生成的压缩文件
        ZipFile zipFile = null;
        try {
            zipFile = new ZipFile(outputFile);
            ZipParameters parameters = new ZipParameters();
            //设置压缩方式,默认是COMP_DEFLATE
            parameters.setCompressionMethod(Zip4jConstants.COMP_DEFLATE);
            //设置压缩级别,默认为0（即不压缩）
            parameters.setCompressionLevel(Zip4jConstants.DEFLATE_LEVEL_NORMAL);
            //设置压缩密码（至少3步）
            //设置加密文件
            parameters.setEncryptFiles(true);
            //设置加密方式（必须要有加密算法） //设置AES加密方式
            parameters.setEncryptionMethod(Zip4jConstants.ENC_METHOD_AES);
            parameters.setAesKeyStrength(Zip4jConstants.AES_STRENGTH_256);
            //设置压缩的密码
            parameters.setPassword("111");
            // 要打包的文件夹
            File currentFile = new File(inputFile);
            File[] fs = currentFile.listFiles();
            // 遍历test文件夹下所有的文件、文件夹
            for (File f : fs) {
                if (f.isDirectory()) {
                    zipFile.addFolder(f.getPath(), parameters);
                } else {
                    zipFile.addFile(f, parameters);
                }
            }
        } catch (ZipException e) {
            e.printStackTrace();
        }

    }


    /**
     * zip文件下删除文件
     * @param inputFile  D:\test1.zip 要删除的压缩包
     * @param deleteFile  logger/error.2021-08-20.log  删除压缩包下路径的文件
     */
    public static void deleteFile(String inputFile,String deleteFile) {
        try {
            ZipFile zipFile = new ZipFile(inputFile);
            zipFile.removeFile(deleteFile);
        } catch (ZipException e) {
            e.printStackTrace();
        }
    }

    /**
     * 向zip文件下添加文件
     * @param inputFile    D:\test1.zip 要添加文件的压缩包
     * @param addFile logger/error.2021-08-20.log  要添加到压缩包下路径的文件路径  如果logger目录不存在，他会递归生成
     *
     * */
    public static void addFile(String inputFile,String addFile){
        InputStream is = null;
        try {
            ZipFile zip = new ZipFile(inputFile);
            ZipParameters para = new ZipParameters();
            para.setCompressionMethod(Zip4jConstants.COMP_DEFLATE);
            para.setFileNameInZip(addFile);
            para.setSourceExternalStream(true);
            //可以根据自己的需求来改变字节输入流 需要一个添加文件的路径
            is = new ByteArrayInputStream(new String("这是文件内容").getBytes());
            //is = new FileInputStream(text);
            zip.addStream(is, para);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (is != null) {
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }



    /*public static void main(String[] args) {

        //ZipUtil.zipFile("D:/home/jar/data/durable/18/26/1077/43350","D:/home/jar/data/durable/18/26/1077/43350.zip");
        try {

            ZipUtil.unzip("G:\\新建文件夹\\ZB-LX-28c92a7f-6818-11ee-8c32-231f735b5190.zip","G:\\新建文件夹","");
        }catch (Exception e){

        }
    }*/

}
